package com.imu.purse.api.controller;

import com.imu.common.exception.ErrorDesc;
import com.imu.common.exception.ErrorUtil;
import com.imu.common.utils.R;
import com.imu.common.validator.ValidatorUtils;
import com.imu.common.validator.group.UpdateGroup;
import com.imu.constant.Constant;
import com.imu.purse.config.PhoneValidate;
import com.imu.purse.modules.app.entity.ImuUserEntity;
import com.imu.purse.modules.app.entity.ImuUserIdentityEntity;
import com.imu.purse.modules.app.entity.ImuUserLoginEntity;
import com.imu.purse.modules.app.entity.UserCheckEntity;
import com.imu.purse.modules.app.form.*;
import com.imu.purse.modules.app.service.*;
import com.imu.purse.modules.base.entity.DictInfo;
import com.imu.purse.modules.base.service.DictInfoService;
import com.imu.purse.modules.sms.SMSCache;
import com.imu.purse.modules.sms.SMSMessage.Type;
import com.imu.purse.modules.trade.entity.FundEntity;
import com.imu.purse.modules.trade.service.FundService;
import com.imu.security.ISessionTokenProvider;
import com.imu.security.SessionKeys;
import com.imu.security.SessionObject;
import com.imu.security.SessionTokenProviderFactory;
import com.imu.utils.CheckMobile;
import com.xiaoleilu.hutool.bean.BeanUtil;
import com.xiaoleilu.hutool.crypto.SecureUtil;
import com.xiaoleilu.hutool.util.StrUtil;
import cz.mallat.uasparser.UserAgentInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * 登陆接口
 * @author chenshun
 * @email sunlightcs@gmail.com
 * @date 2017-03-26 17:27
 */
@RestController
@RequestMapping("/api")
@Api(tags="登陆接口")
public class ApiLoginController extends ApiAbstractController
{
    @Autowired
    private ImuUserService imuUserService;
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    @Autowired
    private ImuUserLoginService imuUserLoginService;
    
    @Autowired
    private FundService fundService;
    
    @Autowired
    private SMSCache cache;
    
    @Autowired
	private ImuUserIdentityService imuUserIdentityService;

    @Autowired
    private DictInfoService dictInfoService;
    
    @Autowired
    private UserCheckService userCheckService;

    @Autowired
    private CoreService coreService;
  

    @PostMapping("login")
    @ApiOperation("登陆")
    public R login(@RequestBody LoginForms form, HttpServletRequest request, HttpServletResponse response)
    {

        //表单校验
        ValidatorUtils.validateEntity(form);
        //随机选择核心钱包
        String moneyAddrStr = coreService.getCoreAddress();
        ImuUserEntity entity = imuUserService.login(form.getPhone(),moneyAddrStr);
        if(entity == null) {
            return ErrorUtil.errorMesg(request,ErrorDesc.PHONE_OR_PWD_REG);
        }
        if(StrUtil.isNotEmpty(entity.getSalt()) &&  !entity.getPwd().
                equals(new Sha256Hash(form.getPwd(), entity.getSalt()).toHex())){//针对老用户
            return ErrorUtil.errorMesg(request,ErrorDesc.PHONE_OR_PWD_REG);
        }else if(StrUtil.isEmpty(entity.getSalt()) && !entity.getPwd().equals(form.getPwd())){//针对新用户
            return ErrorUtil.errorMesg(request,ErrorDesc.PHONE_OR_PWD_REG);
        }
        //如果密码为123456或654321的md5，则要求用户跳转到忘记密码页面修改密码
        if (Constant.MD5_123456.equals(entity.getPwd()) || Constant.MD5_654321.equals(entity.getPwd())){
            return ErrorUtil.errorMesg(request,ErrorDesc.PASS_SIMPLE);
        }

        if(entity.getState() != Constant.USER_ENABLE){//该账号被禁用聊
            return ErrorUtil.errorMesg(request,ErrorDesc.USER_DISABLE);
        }

        //验证手机验证码
        /*String type = String.valueOf(form.getType());
        Type messageType = PhoneValidate.Authentication(type);
        if(messageType == null){
            return ErrorUtil.errorMesg(request,ErrorDesc.TYPE_ERR);
        }
        String a = cache.findCode(messageType.getType(), form.getPhone());
        if(StringUtils.isNotEmpty(a)){
            if(!a.equals(form.getPhoneCode())){
                return ErrorUtil.errorMesg(request,ErrorDesc.ACODE_ERROR);
            }
        }else {
            return ErrorUtil.errorMesg(request,ErrorDesc.ACODE_ERROR);
        }*/
        //验证图片验证码是否正确
        String picPass = form.getCode().toLowerCase();
        if(StrUtil.isEmpty(redisTemplate.opsForValue().get(picPass))){
        	return ErrorUtil.errorMesg(request,ErrorDesc.PHOTO_ACODE_ERROR);
        }

        String agent = request.getHeader(SessionKeys.AGENT.toString()); //用户登录终端
        String term = null;
        
        if(StrUtil.isNotBlank(agent))
        {
        	UserAgentInfo userAgent = CheckMobile.getAgent(agent);
        	if(null != userAgent)
        	{
        		term = userAgent.getOsName();
        	}
        }
        boolean mobile = CheckMobile.check(agent);
        String secret = SecureUtil.md5(entity.getId() + (mobile ? Constant.MOBILE : Constant.PC));
        
        ISessionTokenProvider sessionProvider = SessionTokenProviderFactory.getSessionTokenProvider();
        //直接剔除所有pc和移动端的   防止pc端和移动端同时在线
        String eliminate = SecureUtil.md5(entity.getId() + Constant.MOBILE);
        sessionProvider.removeSession(eliminate);
        eliminate = SecureUtil.md5(entity.getId() + Constant.PC);
        sessionProvider.removeSession(eliminate);
        //剔除上次登录记录
        //sessionProvider.removeSession(secret);
        //保存Session会话
        SessionObject session = sessionProvider.setSession(String.valueOf(entity.getId()), term, form.getPhone(), String.valueOf(entity.getGender()), mobile);
        response.setHeader(SessionKeys.TOKEN.toString(), session.getToken());
        response.setHeader(SessionKeys.SECRET.toString(), secret);
        
		//保存登陆信息
		ImuUserLoginEntity imuUserLogin = new ImuUserLoginEntity();
		imuUserLogin.setUserId(entity.getId());
		imuUserLogin.setAccount(entity.getPhone());
		imuUserLogin.setToken(session.getToken());
		imuUserLoginService.save(imuUserLogin);

        //删除图片验证码缓存
        redisTemplate.delete(picPass);
		//增加身份宝信息 获取该用户的身份信息
        //支付密码默认设置
        int payPwdFlag = 1; //默认为已设置
        if(StringUtils.isEmpty(entity.getPayPwd())){
            payPwdFlag = 0; //没有设置
        }
        
        return R.ok(1).put(SessionKeys.TOKEN.toString(), session.getToken())
                .put(SessionKeys.SECRET.toString(), secret).put("payPwdFlag",payPwdFlag);
               // .put("secretFlag",secretFlag);
    }

    @PostMapping("forgetPwd")
    @ApiOperation("忘记密码")
    public R forgetPwd(HttpServletRequest request,@RequestBody ForgetPwdForm form)
    {
        //表单校验
        ValidatorUtils.validateEntity(form);
        //判断是否有该用户
        ImuUserEntity imuUser=imuUserService.queryByMobile(form.getPhone());
        if(imuUser == null){
            return ErrorUtil.errorMesg(request,ErrorDesc.PHONE_ERR);
        }
        String picPass = form.getCodes().toLowerCase();
        //验证图片验证码是否正确
        if(StrUtil.isEmpty(redisTemplate.opsForValue().get(picPass))){
            return ErrorUtil.errorMesg(request,ErrorDesc.PHOTO_ACODE_ERROR);
        }
        //验证手机验证码
        String type = String.valueOf(form.getType());
        Type messageType = PhoneValidate.Authentication(type);
        if(messageType == null){
        	return ErrorUtil.errorMesg(request,ErrorDesc.TYPE_ERR);
        }
        String phone = StrUtil.isEmpty(imuUser.getInterPhone()) ? form.getPhone() : imuUser.getInterPhone();
        String a = cache.findCode(messageType.getType(), phone);
        if(StringUtils.isNotEmpty(a)){
            if(!a.equals(form.getCode())){
                return ErrorUtil.errorMesg(request,ErrorDesc.ACODE_ERROR);
            }
        }else {
            return ErrorUtil.errorMesg(request,ErrorDesc.ACODE_ERROR);
        }
        String salt = RandomStringUtils.randomAlphanumeric(20);
        imuUser.setPwd(new Sha256Hash(form.getPwd(), salt).toHex());
        imuUser.setSalt(salt);
        imuUserService.updates(imuUser,imuUser.getId());
        //忘记密码不需要解除身份宝信息
        redisTemplate.opsForHash().delete("googleQrCode", form.getPhone());
        //删除图片验证码
        redisTemplate.delete(picPass);
        //删除手机验证码
        cache.delCode(type,phone);
        return R.ok(1);
    }
    
    
    @PostMapping("index")
    @ApiOperation("首页")//完善个人资料也可调用
    public R index(HttpServletRequest request,@RequestHeader("X-IMU-SECRET") String secret, @RequestHeader("X-IMU-SESSION") String token)
    {
        R r =R.ok(1);
        SessionObject session = com.imu.security.SessionTokenProviderFactory.getSessionTokenProvider().getCurrent(secret, token);
        if(session==null){
        	return ErrorUtil.errorMesg(request,ErrorDesc.TOKEN_EMPTY);
        }
        ImuUserEntity userEntity = imuUserService.findById(Long.valueOf(session.getId()));
        userEntity.setPayPwd(null);
        userEntity.setPwd(null);
        userEntity.setSalt(null);

        FundEntity fund = fundService.findByUserId(Long.parseLong(session.getId()));

        List<DictInfo> infoList = dictInfoService.findCahceByCode("VIRTUAL_CURRENCY");
        
        r.put("userCheckEntity", userCheckService.findByUserId(Long.parseLong(session.getId()))); //需要添加校验信息
        r.put("imuUserEntity", userEntity);
        r.put("fund", fund);
        r.put("virtualCurrency",infoList);
        return r;
    }
    
    @PostMapping("userDetailInfo")
    @ApiOperation("完善用户信息")
    public R userDetailInfo(HttpServletRequest request,@RequestBody UserDetailInfoForm form,@RequestHeader("X-IMU-SECRET") String secret, @RequestHeader("X-IMU-SESSION") String token)
    {
    	
        //表单校验
        ValidatorUtils.validateEntity(form, UpdateGroup.class);
        SessionObject session = com.imu.security.SessionTokenProviderFactory.getSessionTokenProvider().getCurrent(secret, token);
        if(session==null){
        	return ErrorUtil.errorMesg(request,ErrorDesc.TOKEN_EMPTY);
        }
        
        ImuUserEntity imuUser = new ImuUserEntity();
        BeanUtil.copyProperties(form, imuUser);
        imuUser.setId(Long.parseLong(session.getId()));
        /*imuUser.setNickName(form.getNickName());
        imuUser.setAddress(form.getAddress());
        imuUser.setRealName(form.getRealName());
        imuUser.setCardNo(form.getCardNo());*/
        imuUserService.update(imuUser);
        return R.ok(1);
    }
    
    /**
     * 修改支付密码
     */
    @PostMapping("updatePayPwd")
    @ApiOperation("修改支付密码")
    public R updatePayPwd(HttpServletRequest request,@RequestBody UpdatePayPwdForm form,@RequestHeader("X-IMU-SECRET") String secret, @RequestHeader("X-IMU-SESSION") String token)
    {
        //表单校验
        ValidatorUtils.validateEntity(form);
        SessionObject session = com.imu.security.SessionTokenProviderFactory.getSessionTokenProvider().getCurrent(secret, token);
        if(session == null){
        	return ErrorUtil.errorMesg(request,ErrorDesc.TOKEN_EMPTY);
        }
        ImuUserEntity imuUser = imuUserService.findById(Long.parseLong(session.getId()));
        //验证google身份认证码
        /*Object QrCode = redisTemplate.opsForHash().get("googleQrCode", imuUser.getPhone());
        if(null!=QrCode){
        	long t = System.currentTimeMillis();
        	GoogleAuthenticatorConfig ga = new GoogleAuthenticatorConfig();
    		ga.setWindowSize(5); 
    		boolean r = ga.check_code(QrCode.toString(), Long.parseLong(form.getGoogleQrCode()), t);
    		if(!r){
    			return ErrorUtil.errorMesg(request,ErrorDesc.Identity_Iuthentication_Code);
    		}
        }else {
        	return ErrorUtil.errorMesg(request,ErrorDesc.Identity_Iuthentication_Code);
		}*/
        String picPass = form.getPicPass().toLowerCase();
        if(StrUtil.isEmpty(redisTemplate.opsForValue().get(picPass))){//增加图片验证码
            return ErrorUtil.errorMesg(request,ErrorDesc.PHOTO_ACODE_ERROR);
        }
        //验证手机验证码
        String type = String.valueOf(form.getType());
        Type messageType = PhoneValidate.Authentication(type);
        if(messageType == null)
        {
            return ErrorUtil.errorMesg(request,ErrorDesc.TYPE_ERR);
        }
        String phone = null;
        try {
            phone = StringUtils.isEmpty(imuUser.getInterPhone()) ? imuUser.getPhone() : imuUser.getInterPhone();
            String a = cache.findCode(messageType.getType(), phone);
            if(StringUtils.isNotEmpty(a)){
                if(!a.equals(form.getCode())){
                    return ErrorUtil.errorMesg(request,ErrorDesc.ACODE_ERROR);
                }
            }else {
                return ErrorUtil.errorMesg(request,ErrorDesc.ACODE_ERROR);
            }
        }
        catch (Exception e)
        {
            return ErrorUtil.errorMesg(request,ErrorDesc.ACODE_ERROR);
        }

    	redisTemplate.delete(imuUser.getPhone());
        imuUser = new ImuUserEntity();
        imuUser.setId(Long.parseLong(session.getId()));
        imuUser.setPayPwd(new Sha256Hash(form.getPayPwd()).toHex());
        imuUserService.update(imuUser);

        //删除图片验证码
        redisTemplate.delete(picPass);
        //删除手机验证码
        cache.delCode(type,phone);
        return R.ok(1);
    }
    
    /**
     * 校验单前的phone是否有效
     */
    @PostMapping("checkIdentityCode")
    @ApiOperation("判断用户手机号")
    public R checkIdentityCode(@RequestBody CheckIdentityCode form)
    {
    	Object QrCode =null;

    	try{
    		QrCode = redisTemplate.opsForHash().get("googleQrCode",form.getPhone());
    	}catch (Exception e) {
			e.printStackTrace();
		}
        if(null==QrCode){
        	//如果为空  则有可能是redis挂了 查询数据库看有没有值
        	ImuUserEntity imuUser = imuUserService.queryByMobile(form.getPhone());
        	if(null!=imuUser){//表示当前用户存在   则查询密钥表
        		ImuUserIdentityEntity entity = new ImuUserIdentityEntity();
            	entity.setUserId(imuUser.getId());
            	entity=imuUserIdentityService.selectByUserId(entity);
            	if(null!=entity){
            		if(entity.getSecretKey().length()<1){
            			return R.ok(0);
            		}else {
            			return R.ok(1);
					}
            	}else {
            		return R.ok(0);
				}
        	}else {
        		return R.ok(0);
			}
        }
    	return R.ok(1);
    }
}